﻿using System.Text;
using System;
using System.Xml;
using Marbles.Data;
using System.Data;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Marbles.CMS.Configuration;

using System.Collections;
using Marbles.CMS.Core;
using System.IO;

namespace Marbles.CMS.ContentTypes
{
    public class ContentManagerBase
    {
        public ContentControllerConfiguration ContentSettings
        {
            get
            {
                ContentControllerConfiguration config = System.Web.Configuration.WebConfigurationManager.GetSection("MarblesCMS/ContentController") as ContentControllerConfiguration;
                return config;
            }
        }

        public bool TemplateExists(string TemplateName)
        {
            DataSource dbc = new DataSource(this.ContentSettings.connectionString);
            DataSourceCommand cmd = new DataSourceCommand("SELECT templatesourcepath FROM Templates WHERE templatename = @templatename");
            cmd.Parameters.Add("@templatename", TemplateName);

            DataTable dt = dbc.FetchDataTable(cmd);

            if (dt.Rows.Count > 0) { return true; }

            return false;
        }

        public string GetTemplateSourcePath(string TemplateName)
        {
            DataSource dbc = new DataSource(this.ContentSettings.connectionString);
            DataSourceCommand cmd = new DataSourceCommand("SELECT templatesourcepath FROM Templates WHERE templatename = @templatename");
            cmd.Parameters.Add("@templatename", TemplateName);

            DataTable dt = dbc.FetchDataTable(cmd);

            if (dt.Rows.Count > 0) { return dt.Rows[0]["templatesourcepath"].ToString(); }

            return string.Empty;
        }

        public PageDefinition GetPageDefinition(string PageName)
        {
            DataSource dbc = new DataSource(this.ContentSettings.connectionString);
            DataSourceCommand cmd = new DataSourceCommand("SELECT a.anonymouscontent, a.visible, a.pagetype, a.parentpageid, a.pageid, a.keywords, a.description, a.templatename, a.title, b.templatesourcepath, b.themename FROM Page a INNER JOIN Templates b ON a.templatename = b.templatename WHERE a.pageid = @pageid");
            cmd.Parameters.Add("@pageid", PageName);

            DataTable dt = dbc.FetchDataTable(cmd);

            if (dt.Rows.Count > 0)
            {
                PageDefinition info = new PageDefinition();
                info.Anonymous = Convert.ToBoolean(dt.Rows[0]["anonymouscontent"]);
                info.ParentPageName = dt.Rows[0]["parentpageid"].ToString();
                info.PageName = dt.Rows[0]["pageid"].ToString();
                info.TemplateName = dt.Rows[0]["templatename"].ToString();
                info.TemplateSourcePath = dt.Rows[0]["templatesourcepath"].ToString();
                info.ThemeName = dt.Rows[0]["themename"].ToString();
                info.Title = dt.Rows[0]["title"].ToString();
                info.Description = dt.Rows[0]["description"].ToString();
                info.Keywords = dt.Rows[0]["keywords"].ToString();
                info.Visible = Convert.ToBoolean(dt.Rows[0]["visible"]);
                info.Renderer = GetPageRendererFromType(dt.Rows[0]["pagetype"].ToString());
                return info;
            }

            return null;
        }

        public void InsertDefinition(PageDefinition Definition)
        {
            DataSource dbc = new DataSource(this.ContentSettings.connectionString);
            DataSourceCommand cmd = new DataSourceCommand("INSERT INTO Page (anonymouscontent, pagetype, visible, parentpageid,pageid,templatename,title,description,keywords) VALUES (@anonymouscontent, @pagetype,@visible, @parentpageid,@pageid,@templatename,@title,@description,@keywords)");
            cmd.Parameters.Add("@title", Definition.Title);
            cmd.Parameters.Add("@anonymouscontent", Definition.Anonymous);
            cmd.Parameters.Add("@pagetype", Definition.Renderer.PageType);
            cmd.Parameters.Add("@visible", Definition.Visible);
            cmd.Parameters.Add("@parentpageid", Definition.ParentPageName);
            cmd.Parameters.Add("@templatename", Definition.TemplateName);
            cmd.Parameters.Add("@description", Definition.Description);
            cmd.Parameters.Add("@keywords", Definition.Keywords);
            cmd.Parameters.Add("@pageid", Definition.PageName);
            dbc.ExecuteCommand(cmd);
        }

        public void UpdateDefinition(PageDefinition Definition)
        {
            DataSource dbc = new DataSource(this.ContentSettings.connectionString);
            DataSourceCommand cmd = new DataSourceCommand("UPDATE Page SET anonymouscontent = @anonymouscontent, pagetype = @pagetype, visible = @visible, parentpageid = @parentpageid, templatename = @templatename, title = @title, description = @description, keywords = @keywords WHERE pageid = @pageid");
            cmd.Parameters.Add("@visible", Definition.Visible);
            cmd.Parameters.Add("@anonymouscontent", Definition.Anonymous);
            cmd.Parameters.Add("@pagetype", Definition.Renderer.PageType);
            cmd.Parameters.Add("@title", Definition.Title);
            cmd.Parameters.Add("@parentpageid", Definition.ParentPageName);
            cmd.Parameters.Add("@templatename", Definition.TemplateName);
            cmd.Parameters.Add("@description", Definition.Description);
            cmd.Parameters.Add("@keywords", Definition.Keywords);
            cmd.Parameters.Add("@pageid", Definition.PageName);
            dbc.ExecuteCommand(cmd);
        }

        public PageDefinition GetPageDefinition(Uri uri)
        {
            return GetPageDefinition(GetPageName(uri));
        }

        public Dictionary<string, string> GetAvailableTemplates()
        {
            Dictionary<string, string> items = new Dictionary<string, string>();
            DataSource dbc = new DataSource(this.ContentSettings.connectionString);
            DataSourceCommand cmd = new DataSourceCommand("SELECT title, templatename FROM Templates ORDER BY title ASC");
            DataTable dt = dbc.FetchDataTable(cmd);

            foreach (DataRow dr in dt.Rows)
            {
                items.Add(dr["templatename"].ToString(), dr["title"].ToString());
            }

            return items;
        }

        public TemplateDefinition GetTemplateDefinition(string templatename)
        {
            TemplateDefinition def = null;
            DataSource dbc = new DataSource(this.ContentSettings.connectionString);
            DataSourceCommand cmd = new DataSourceCommand("SELECT  templatename, templatesourcepath, themename, title FROM Templates WHERE templatename = @templatename");
            cmd.Parameters.Add("@templatename", templatename);
            DataTable dthead = dbc.FetchDataTable(cmd);

            if (dthead.Rows.Count <= 0) { return null; }

            def = new TemplateDefinition(dthead.Rows[0]["title"].ToString(), dthead.Rows[0]["templatename"].ToString(), dthead.Rows[0]["templatesourcepath"].ToString(), dthead.Rows[0]["themename"].ToString());

            DataSourceCommand cmd1 = new DataSourceCommand("SELECT contentid, title, editorheight FROM TemplateContent WHERE templatename = @templatename ORDER BY title ASC");
            cmd1.Parameters.Add("@templatename", templatename);
            DataTable dtitems = dbc.FetchDataTable(cmd1);

            foreach (DataRow dr in dtitems.Rows)
            {
                
                def.ContentIds.Add(new TemplateContentDefinition(dr["contentid"].ToString(), dr["title"].ToString(), Convert.ToInt32(dr["editorheight"])));
            }

            
            return def;

        }

        public Dictionary<string, string> GetAllPages()
        {
            DataSource dbc = new DataSource(this.ContentSettings.connectionString);
            DataSourceCommand cmd = new DataSourceCommand("SELECT pageid, title FROM Page ORDER BY title ASC");
            DataTable dt = dbc.FetchDataTable(cmd);
            Dictionary<string, string> items = new Dictionary<string, string>();

            foreach (DataRow dr in dt.Rows)
            {
                items.Add(dr["pageid"].ToString(), dr["title"].ToString());
            }

            return items;

        }

        public void GenerateSiteMap()
        {
            string mappedfilename = HttpContext.Current.Server.MapPath("/Web.sitemap");
            DataSource dbc = new DataSource(this.ContentSettings.connectionString);
            DataSourceCommand cmd = new DataSourceCommand("SELECT DISTINCT a.parentpageid AS pageid, COALESCE(b.title, '') AS title, COALESCE(b.description, '') AS description FROM Page a LEFT JOIN Page b ON a.parentpageid = b.pageid WHERE a.parentpageid = ''");
            DataTable dt = dbc.FetchDataTable(cmd);
            XmlDocument xdoc = new XmlDocument();
            XmlDeclaration docroot = xdoc.CreateXmlDeclaration("1.0", "utf-8", "yes");
            XmlNode root = xdoc.CreateElement("siteMap", "http://schemas.microsoft.com/AspNet/SiteMap-File-1.0");

            foreach (DataRow dr in dt.Rows)
            {
                if (dr["pageid"].ToString() != string.Empty)
                {
                    XmlNode node = CreateSiteMapNode(xdoc, dr["pageid"].ToString(), dr["title"].ToString(), dr["description"].ToString(), string.Empty, string.Empty);
                    GenerateNodeChildren(xdoc, node, dr, dbc);
                    root.AppendChild(node);
                }
                else
                {
                    GenerateNodeChildren(xdoc, root, dr, dbc);
                }
            }

            xdoc.AppendChild(docroot);
            xdoc.AppendChild(root);

            if (File.Exists(mappedfilename))
            {
                if (File.Exists(mappedfilename + ".bak")) { File.Delete(mappedfilename + ".bak"); }
                File.Copy(mappedfilename, mappedfilename + ".bak");
                File.Delete(mappedfilename);
            }

            xdoc.Save(mappedfilename);

        }

        private XmlNode CreateSiteMapRootNode(XmlDocument xdoc)
        {
            XmlNode node = xdoc.CreateElement("siteMap", "http://schemas.microsoft.com/AspNet/SiteMap-File-1.0");
            return node;
        }

        public XmlNode CreateSiteMapNode(XmlDocument xdoc, string url, string title, string description, string resourceKey, string roles)
        {
            XmlElement node = xdoc.CreateElement("siteMapNode");
            node.Attributes.Append(CreateAttribute(xdoc, "url", url));
            node.Attributes.Append(CreateAttribute(xdoc, "title", title));
            node.Attributes.Append(CreateAttribute(xdoc, "description", description));
            node.Attributes.Append(CreateAttribute(xdoc, "resourceKey", resourceKey));
            node.Attributes.Append(CreateAttribute(xdoc, "roles", roles));
            return node;
        }

        private string GetStringValue(IList list)
        {
            if (list == null) { return string.Empty; }
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < list.Count; i++)
            {
                if (i > 0) { sb.Append(","); }
                sb.Append(list[i].ToString());
            }
            return sb.ToString();
        }

        private XmlAttribute CreateAttribute(XmlDocument xdoc, string name, string value)
        {
            XmlAttribute attr = xdoc.CreateAttribute(name);
            attr.InnerText = value;
            return attr;
        }


        private void GenerateNodeChildren(XmlDocument xdoc, XmlNode root, DataRow row, DataSource dbc)
        {
            DataSourceCommand cmd = new DataSourceCommand("SELECT pageid, title, description FROM Page a WHERE a.parentpageid = @pageid");
            cmd.Parameters.Add("@pageid", row["pageid"].ToString());
            DataTable dt = dbc.FetchDataTable(cmd);

            foreach (DataRow dr in dt.Rows)
            {
                XmlNode node = CreateSiteMapNode(xdoc, dr["pageid"].ToString(), dr["title"].ToString(), dr["description"].ToString(), string.Empty, string.Empty);
                GenerateNodeChildren(xdoc, node, dr, dbc);
                root.AppendChild(node);
            }

        }

        public PageRenderer GetPageRenderer(string PageName)
        {
            DataSource dbc = new DataSource(this.ContentSettings.connectionString);
            DataSourceCommand cmd = new DataSourceCommand("SELECT b.* FROM Page a INNER JOIN PageType b ON a.pagetype = b.pagetype WHERE a.pageid = @pageid");
            cmd.Parameters.Add("@pageid", PageName);
            DataTable dt = dbc.FetchDataTable(cmd);
            PageRenderer info = null;

            if (dt.Rows.Count > 0)
            {

                info = new PageRenderer();
                info.Editor = dt.Rows[0]["editor"].ToString();
                info.PageType = dt.Rows[0]["pagetype"].ToString();
                info.Renderer = dt.Rows[0]["renderer"].ToString();
                info.RendererType = dt.Rows[0]["renderertype"].ToString();
                info.Title = dt.Rows[0]["title"].ToString();
            }

            return info;
        }

        public PageRenderer GetPageRendererFromType(string PageType)
        {
            DataSource dbc = new DataSource(this.ContentSettings.connectionString);
            DataSourceCommand cmd = new DataSourceCommand("SELECT a.* FROM PageType a WHERE a.pagetype = @pagetype");
            cmd.Parameters.Add("@pagetype", PageType);
            DataTable dt = dbc.FetchDataTable(cmd);
            PageRenderer info = null;

            if (dt.Rows.Count > 0)
            {
                info = new PageRenderer();
                info.Editor = dt.Rows[0]["editor"].ToString();
                info.PageType = dt.Rows[0]["pagetype"].ToString();
                info.Renderer = dt.Rows[0]["renderer"].ToString();
                info.RendererType = dt.Rows[0]["renderertype"].ToString();
                info.Title = dt.Rows[0]["title"].ToString();
            }

            return info;
        }

        public PageRenderer[] GetInstalledRenderers()
        {
            DataSource dbc = new DataSource(this.ContentSettings.connectionString);
            DataSourceCommand cmd = new DataSourceCommand("SELECT a.* FROM PageType a ORDER BY title ASC");
            DataTable dt = dbc.FetchDataTable(cmd);
            List<PageRenderer> list = new List<PageRenderer>();

            if (dt.Rows.Count > 0)
            {
                foreach (DataRow dr in dt.Rows)
                {
                    PageRenderer info = new PageRenderer();
                    info.Editor = dr["editor"].ToString();
                    info.PageType = dr["pagetype"].ToString();
                    info.Renderer = dr["renderer"].ToString();
                    info.RendererType = dr["renderertype"].ToString();
                    info.Title = dr["title"].ToString();
                    list.Add(info);
                }
            }

            return list.ToArray();
        }


        public Dictionary<string, string> GetPageTypeEditors()
        {
            Dictionary<string, string> items = new Dictionary<string, string>();
            DataSource dbc = new DataSource(this.ContentSettings.connectionString);
            DataSourceCommand cmd = new DataSourceCommand("SELECT pagetype, title, editor FROM PageType ORDER BY title ASC");
            DataTable dt = dbc.FetchDataTable(cmd);

            foreach (DataRow dr in dt.Rows)
            {
                items.Add(dr["pagetype"].ToString(), dr["title"].ToString());
            }

            return items;
        }


        public string GetPageName(Uri uri)
        {
            string document = uri.Segments[0] + uri.Segments[1].ToLower();
            document = document.Replace(".aspx", string.Empty);
            return document;
        }
        

    }
}
